package com.fx.zmlzml.config;

import com.fx.zmlzml.filter.JwtTokenFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.authentication.AuthenticationManagerFactoryBean;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    /**
     * 配置 Spring Security 安全过滤链
     * @param http HttpSecurity对象，用于配置Web安全
     * @return SecurityFilterChain 安全过滤链，定义了应用的安全策略
     * @throws Exception 配置过程中可能抛出的异常
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtTokenFilter jwtTokenFilter) throws Exception {
        http
                // 添加JWT过滤器
                .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)
                // 授权配置
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/api/sys/login").permitAll()  // 允许访问 /api/sys/login 无需认证
                        .anyRequest().authenticated() // 其他所有请求都需要认证
                )
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态会话管理
                )
                .headers(headers -> headers
                        .contentSecurityPolicy(csp -> csp
                                .policyDirectives("default-src 'self'")
                        )
                        .frameOptions(frame -> frame.sameOrigin())           // 防止点击劫持
                        .httpStrictTransportSecurity(hsts -> hsts            // HSTS
                                .includeSubDomains(true)
                                .maxAgeInSeconds(31536000)
                        )
                        .xssProtection(xss -> xss.disable())              // XSS 保护
                )
                .csrf(csrf -> csrf.disable()
                );
        return http.build();
    }

    /**
     * 忽略静态资源
     * @return
     */
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers("/css/**", "/js/**", "/images/**", "/webjars/**");
    }


    /**
     * 配置密码编码器
     * @return PasswordEncoder 返回BCrypt密码编码器实例，用于密码的加密和验证
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置认证管理器工厂Bean
     * @return AuthenticationManagerFactoryBean 返回认证管理器工厂Bean实例，用于创建认证管理器
     */
    @Bean
    public AuthenticationManagerFactoryBean authenticationManager() {
        return new AuthenticationManagerFactoryBean();
    }
}